#include "unp.h"


// clear && ./tcpcli < unp.h
int main(int argc, char * argv[]) {
	char *host = "127.0.0.1";
	if (argc >= 2) {
		host = argv[1];
	}

	SA_IN serv_addr;
	int sockfd;

	Signal(SIGPIPE, sig_pipe);

	printf("cli pid=%d\n", getpid());
	sockfd = Socket(AF_INET, SOCK_STREAM, 0);

	// -----addition----set SO_RCVLOWAT
	// 如果 发送513bytes， mss=512， 分成 （512 + 1） 2次发送，
	// 接收端设置了 rcvlowat = 10, 那么首先接收到512个字节，后续的1个字节，在rcvbuf中，无法读取，知道接收到更多的内容超过 10字节 。 这样理解是否正确
	// 我再 unp chapter7中看到这样一句：The receive low-water mark is the amount of data that must be in the socket receive buffer for select to return "readable."
	int rcvlowat = 5;
	int optlen = sizeof(rcvlowat);
	if (setsockopt(sockfd, SOL_SOCKET, SO_RCVLOWAT, &rcvlowat, optlen) < 0) {
		printf("Error setsockopt \n");
	} else
		printf("set SO_RCVLOWAT = %d, no response until >=%d char input\n", rcvlowat, rcvlowat);
	// -----addition----set SO_RCVLOWAT

	bzero((char*)&serv_addr, sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(SERV_PORT);
	Inet_pton(AF_INET, host, &(serv_addr.sin_addr));
	Connect(sockfd, (SA*)&serv_addr, sizeof(serv_addr));

	// -----addition----get localo ip/port
	struct sockaddr_in localaddr;
	socklen_t addrlen = sizeof(localaddr);
	if ((getsockname(sockfd,  (SA*)&localaddr, &addrlen)) < 0) {
		perror("ERROR getsockname");
		exit(1);
	} else {
		char  localip[100];
		char *dst;
		if ((dst = inet_ntop(AF_INET, &(localaddr.sin_addr), localip, 100)) == NULL) {
			perror("ERROR inet_ntop");
			exit(1);
		}
		printf("local ip=%s, port=%d\n", localip, ntohs(localaddr.sin_port));
	}
	// -----addition----get localo ip/port

	str_cli(stdin, sockfd);
	return 0;
}

void str_cli(FILE* fp, int sockfd) {
	char sendline[MAXLINE], recvline[MAXLINE];
	ssize_t n;

	int maxfdp1, stdineof = 0;
	fd_set rset;

	for (;;) {
		FD_ZERO(&rset);
		int fd1 = fileno(fp);
		if (stdineof == 0) {
			FD_SET(fd1, &rset);
		}
		FD_SET(sockfd, &rset);
		maxfdp1 = max(fd1, sockfd) + 1;

		select(maxfdp1, &rset, NULL, NULL, NULL);

		if (FD_ISSET(fd1, &rset)) { // readable
			if (Fgets(sendline, MAXLINE, fp) != NULL) {

				Write(sockfd, sendline, strlen(sendline));
			} else {
				// sleep(10);
				// exit(0);
				printf("all done, now shut down write\n");
				shutdown(sockfd, SHUT_WR);
				FD_CLR(fd1, &rset);
				stdineof = 1;
			}
		}

		if (FD_ISSET(sockfd, &rset)) {
			n = readline(sockfd, recvline, MAXLINE);
			if (n == 0) {
				if (stdineof == 1) {
					printf("normaly exit\n");
					return; //normaly exit;
				}
				printf("server close prematurely\n");
				exit(1);
			} else {
				Fputs(recvline, stdout);
			}
		}
	}
}
